home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / DMO / GargleDMO / MedParamBase / validate.h < prev   
Encoding:
C/C++ Source or Header  |  2001-10-08  |  11.5 KB  |  305 lines

  1. //------------------------------------------------------------------------------
  2. // File: Validate.h
  3. //
  4. // Desc: DirectShow sample code - parameter validation macros.
  5. //
  6. // Copyright (c) 1997-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. // Summary:
  11. //
  12. // V_INAME(interfacename)                - Set the interface name for error display
  13. // V_STRUCTPTR_READ(ptr,type)            - A dwSize struct which we will read
  14. // V_STRUCTPTR_WRITE(ptr,type)           - A dwSize struct which we will read/write
  15. // V_PTR_READ(ptr,type)                  - A typed ptr w/o a dwSize which we will read
  16. // V_PTR_WRITE(ptr,type)                 - A typed ptr w/o a dwSize which we will read/write
  17. // V_PTR_WRITE_OPT(ptr,type)             - An optional typed ptr w/o a dwSize which we will read/write
  18. // V_BUFPTR_READ(ptr,size)               - A variable-size buffer that we will read
  19. // V_BUFPTR_READ_OPT(ptr,size)             - An optional variable-size buffer that we will read
  20. // V_BUFPTR_WRITE(ptr,size)              - A variable-size buffer that we will read/write
  21. // V_BUFPTR_WRITE_OPT(ptr,size)          - An optional variable-size buffer that we will read/write
  22. // V_PTRPTR_WRITE(ptrptr)                - A pointer to a pointer to write to
  23. // V_PTRPTR_WRITE_OPT(ptrptr)            - A pointer to a pointer to write to that is optional
  24. // V_PUNKOUTER(punk)                     - A pointer to a controlling unknown, aggregation supported
  25. // V_PUNKOUTER_NOADD(punk)               - A pointer to a controlling unknown, aggregation not supported
  26. // V_INTERFACE(ptr)                      - A pointer to a COM interface
  27. // V_INTERFACE_OPT(ptr)                  - An optional pointer to a COM interface
  28. // V_REFGUID(ref)                        - A reference to a GUID (type REFGUID)
  29. // V_HWND(hwnd)                             - A window handle
  30. // V_HWNDOPT(hwnd)                         - An optional window handle
  31. //
  32. // For handling different versions of structures:
  33. // 
  34. // V_STRUCTPTR_READ_VER(ptr,ver)         - Begin a struct version block for read access
  35. //                                         At the end, 'ver' will contain the 
  36. //                                         discovered version of the struct
  37. // V_STRUCTPTR_READ_VER_CASE(base,ver)   - Test struct against version ver of
  38. //                                         type 'base'. 
  39. // V_STRUCTPTR_READ_VER_END(base,ptr)    - End a struct version block
  40. //
  41. // V_STRUCTPTR_WRITE_VER(ptr,ver)        - Struct version block for write access
  42. // V_STRUCTPTR_WRITE_VER_CASE(base,ver)
  43. // V_STRUCTPTR_WRITE_VER_END(base,ptr)
  44. //
  45. // The struct version block expects type names of a base type followed by a 
  46. // numeric version, such as
  47. //
  48. // typedef struct { } FOO7;
  49. // typedef struct { } FOO8;
  50. //
  51. // In the header FOO and LPFOO are conditionally typedef'd based on a version
  52. // #define. The DLL will be compiled with the latest version number and hence
  53. // the largest version of the struct.
  54. //
  55. // Since Windows headers are compiled by default with 8-byte alignment, adding
  56. // one DWORD may not cause the size of the structure to change. If this happens
  57. // you will get a 'case label already used' error on one of the VER_CASE macros.
  58. // If this happens, you can get around it by adding a dwReserved field to the 
  59. // end of the struct to force the padding.
  60. //
  61. // 'optional' means the pointer is allowed to be NULL by the interface specification.
  62. //
  63. // Sample usage:
  64. //
  65. // int IDirectMusic::SetFooBarInterface(
  66. //     LPDMUS_REQUESTED_CAPS    pCaps,          // Caps w/ dwSize (read-only)
  67. //     LPVOID                   pBuffer,        // Buffer we will fill in
  68. //     DWORD                    cbSize,         // Size of the buffer
  69. //     PDIRECTMUSICBAR          pBar)           // Callback interface for bar on this buffer
  70. // {
  71. //     V_INTERFACE(IDirectMusic::SetFooBarInterface);
  72. //     V_BUFPTR_WRITE(pBuffer, cbSize);
  73. //     V_INTERFACE(pBar);
  74. //     DWORD dwCapsVer;                         // Must be a DWORD!!!
  75. //
  76. //     V_STRUCTPTR_READ_VER(pCaps, dwCapsVer);
  77. //     V_STRUCTPTR_READ_VER_CASE(DMUS_REQUESTED_CAPS, 7);
  78. //     V_STRUCTPTR_READ_VER_CASE(DMUS_REQUESTED_CAPS, 8);
  79. //     V_STRUCTPTR_READ_VER_END_(DMUS_REQUESTED_CAPS, pCaps);
  80. //
  81. //     // At this point, if we are still in the function we have a valid pCaps
  82. //     // pointer and dwCapsVer is either 7 or 8, indicating the version of
  83. //     // the struct passed in.
  84. //
  85. //     ...
  86. // }
  87. //
  88. #ifndef _VALIDATE_H_
  89. #define _VALIDATE_H_
  90.  
  91.  
  92. #ifdef DBG
  93. #include <stddef.h>
  94.  
  95. #include "debug.h"
  96.  
  97. // To turn on DebugBreak on parameter error, use the following or -DRIP_BREAK in the build:
  98. //
  99. //#define RIP_BREAK 1
  100.  
  101. #ifdef RIP_BREAK
  102. #define _RIP_BREAK DebugBreak();
  103. #else
  104. #define _RIP_BREAK 
  105. #endif
  106.  
  107. #define V_INAME(x) \
  108.     static const char __szValidateInterfaceName[] = #x;                       
  109.  
  110. #define RIP_E_POINTER(ptr) \
  111. {   Trace(-1, "%s: Invalid pointer " #ptr "\n", __szValidateInterfaceName); \
  112.     _RIP_BREAK \
  113.     return E_POINTER; }
  114.  
  115. #define RIP_E_INVALIDARG(ptr) \
  116. {   Trace(-1, "%s: Invalid argument " #ptr "\n", __szValidateInterfaceName); \
  117.     _RIP_BREAK \
  118.     return E_INVALIDARG; }
  119.  
  120. #define RIP_E_HANDLE(h) \
  121. {    Trace(-1, "%s: Invalid handle " #h "\n", __szValidateInterfaceName); \
  122.     _RIP_BREAK \
  123.     return E_HANDLE; }
  124.     
  125. #define RIP_W_INVALIDSIZE(ptr) \
  126. {   Trace(-1, "%s: " #ptr "->dwSize matches no known structure size. Defaulting to oldest structure.\n", \
  127.     __szValidateInterfaceName); \
  128.     _RIP_BREAK \
  129.     }
  130.     
  131. #define RIP_E_INVALIDSIZE(ptr) \
  132. {   Trace(-1, "%s: " #ptr "->dwSize is too small\n", __szValidateInterfaceName); \
  133.     _RIP_BREAK \
  134.     return E_INVALIDARG; }
  135.     
  136. #define RIP_E_BLOCKVSDWSIZE(ptr) \
  137. {   Trace(-1, "%s: " #ptr " does not point to as much memory as " #ptr "->dwSize indicates\n", \
  138.     __szValidateInterfaceName); \
  139.     _RIP_BREAK \
  140.     return E_INVALIDARG; }    
  141.  
  142. // NOTE: The DebugBreak() not in #ifdef is intentional - this is something that
  143. // must be fixed in our code, not an app-generated error.
  144. //
  145. #define V_ASSERT(exp) \
  146. {   if (!(exp)) { \
  147.         Trace(-1, "%s@%s: %s\n", __FILE__, __LINE__, #exp); \
  148.         DebugBreak(); }}
  149.  
  150. #else
  151.  
  152. #define V_INAME(x)
  153. #define RIP_E_POINTER(ptr)          { return E_POINTER; }
  154. #define RIP_E_INVALIDARG(ptr)       { return E_INVALIDARG; }
  155. #define RIP_E_HANDLE(h)                { return E_HANDLE; }
  156. #define RIP_E_BLOCKVSDWSIZE(ptr)    { return E_INVALIDARG; }
  157. #define RIP_W_INVALIDSIZE(ptr)
  158. #define RIP_E_INVALIDSIZE(ptr)      { return E_INVALIDARG; }
  159. #define V_ASSERT(exp)
  160.  
  161. #endif          // DBG
  162.  
  163. // A passed struct we will only read from or may write to. Must be a struct
  164. // with a dwSize.
  165. //
  166. // int foo(CFoo *pFoo)
  167. // ...
  168. // V_STRUCTPTR_READ(pFoo, CFoo);
  169. // V_STRUCTPTR_WRITE(pFoo, CFoo);
  170. //
  171. // Use _PTR_ variants for structs w/o a dwSize
  172. //
  173. #define V_STRUCTPTR_READ(ptr,type) \
  174. {   V_ASSERT(offsetof(type, dwSize) == 0); \
  175.     if (IsBadReadPtr(ptr, sizeof(DWORD)))               RIP_E_BLOCKVSDWSIZE(ptr); \
  176.     if (ptr->dwSize < sizeof(type))                        RIP_E_INVALIDSIZE(ptr); \
  177.     if (IsBadReadPtr(ptr, (ptr)->dwSize))               RIP_E_BLOCKVSDWSIZE(ptr); }
  178.  
  179. #define V_STRUCTPTR_WRITE(ptr,type) \
  180. {   V_ASSERT(offsetof(type, dwSize) == 0); \
  181.     if (IsBadReadPtr(ptr, sizeof(DWORD)))               RIP_E_BLOCKVSDWSIZE(ptr); \
  182.     if (ptr->dwSize < sizeof(type))                        RIP_E_INVALIDSIZE(ptr); \
  183.     if (IsBadWritePtr(ptr, (ptr)->dwSize))              RIP_E_BLOCKVSDWSIZE(ptr); }
  184.  
  185. #define V_PTR_READ(ptr,type) \
  186. { if (IsBadReadPtr(ptr, sizeof(type)))                  RIP_E_POINTER(ptr); }
  187.  
  188. #define V_PTR_WRITE(ptr,type) \
  189. { if (IsBadWritePtr(ptr, sizeof(type)))                 RIP_E_POINTER(ptr); }
  190.  
  191. #define V_PTR_WRITE_OPT(ptr,type) \
  192. { if (ptr) if (IsBadWritePtr(ptr, sizeof(type)))        RIP_E_POINTER(ptr); }
  193.  
  194. // A buffer pointer with separate length (not defined by the pointer type) we will only
  195. // read from or may write to.
  196. //
  197. // int foo(LPVOID *pBuffer, DWORD cbBuffer)
  198. // ...
  199. // V_BUFPTR_READ(pBuffer, cbBuffer);
  200. // V_BUFPTR_WRITE(pBuffer, cbBuffer);
  201. //
  202. #define V_BUFPTR_READ(ptr,len) \
  203. {   if (IsBadReadPtr(ptr, len))                         RIP_E_POINTER(ptr); }
  204.  
  205. #define V_BUFPTR_READ_OPT(ptr,len) \
  206. {    if (ptr) V_BUFPTR_READ(ptr,len); }
  207.  
  208. #define V_BUFPTR_WRITE(ptr,len) \
  209. {   if (IsBadWritePtr(ptr, len))                        RIP_E_POINTER(ptr); }
  210.  
  211. #define V_BUFPTR_WRITE_OPT(ptr,len) \
  212. {    if (ptr) V_BUFPTR_WRITE(ptr,len); }
  213.  
  214. // A pointer to a pointer (such as a pointer to an interface pointer) to return
  215. //
  216. // int foo(IReturnMe **ppRet)
  217. // ...
  218. // V_PTRPTR_WRITE(ppRet);
  219. // V_PTRPTR_WRITE_OPT(ppRet);
  220. //
  221. #define V_PTRPTR_WRITE(ptr) \
  222. {   if (IsBadWritePtr(ptr, sizeof(void*)))              RIP_E_POINTER(ptr); }
  223.  
  224. #define V_PTRPTR_WRITE_OPT(ptr) \
  225. {   if (ptr) if (IsBadWritePtr(ptr, sizeof(void*)))     RIP_E_POINTER(ptr); }
  226.  
  227. // A pointer to a controlling unknown
  228. //
  229. #define V_PUNKOUTER(punk) \
  230. {   if (punk && IsBadCodePtr(punk))                     RIP_E_POINTER(ptr); }
  231.  
  232. // A pointer to a controlling unknown for which we don't support aggregation
  233. //
  234. #define V_PUNKOUTER_NOAGG(punk) \
  235. {   if (punk && IsBadReadPtr(punk, sizeof(IUnknown)))   RIP_E_POINTER(ptr); \
  236.     if (punk) return CLASS_E_NOAGGREGATION; }
  237.  
  238. // Validate an incoming interface pointer. 
  239. //
  240. struct _V_GENERIC_INTERFACE
  241. {
  242.     FARPROC *(__vptr[1]);
  243. };
  244.  
  245. #define V_INTERFACE(ptr) \
  246. {   if (IsBadReadPtr(ptr, sizeof(_V_GENERIC_INTERFACE)))                              RIP_E_POINTER(ptr); \
  247.     if (IsBadReadPtr(*reinterpret_cast<_V_GENERIC_INTERFACE*>(ptr)->__vptr, sizeof(FARPROC))) \
  248.                                                                                       RIP_E_POINTER(ptr); \
  249.     if (IsBadCodePtr(*(reinterpret_cast<_V_GENERIC_INTERFACE*>(ptr)->__vptr)[0]))     RIP_E_POINTER(ptr); }
  250.  
  251. #define V_INTERFACE_OPT(ptr) \
  252. {   if (ptr) V_INTERFACE(ptr); }
  253.  
  254. // Validation for a reference to a GUID, which we only ever read. 
  255. //
  256. #define V_REFGUID(ref) \
  257. {   if (IsBadReadPtr((void*)&ref, sizeof(GUID)))        RIP_E_POINTER((void*)&ref); }
  258.  
  259. // Validation for a window handle
  260. //
  261. #define V_HWND(h) \
  262. {    if (!IsWindow(h))                                    RIP_E_HANDLE(h); }    
  263.  
  264. #define V_HWND_OPT(h) \
  265. {    if (h) if (!IsWindow(h))                            RIP_E_HANDLE(h); }    
  266.  
  267. // Validation for multiple sized structs based on version
  268. //
  269. #define V_STRUCTPTR_READ_VER(ptr,ver) \
  270. {   ver = 7; DWORD *pdw = &ver;  \
  271.     if (IsBadReadPtr(ptr, sizeof(DWORD)))               RIP_E_BLOCKVSDWSIZE(ptr); \
  272.     if (IsBadReadPtr(ptr, (ptr)->dwSize))               RIP_E_BLOCKVSDWSIZE(ptr); \
  273.     switch ((ptr)->dwSize) {
  274.     
  275. #define V_STRUCTPTR_READ_VER_CASE(basetype,ver) \
  276.     case sizeof(basetype##ver) : \
  277.     V_ASSERT(offsetof(basetype##ver, dwSize) == 0); \
  278.     *pdw = ver; break;
  279.     
  280. #define V_STRUCTPTR_READ_VER_END(basetype,ptr) \
  281.     default : if ((ptr)->dwSize > sizeof(basetype##7)) \
  282.     { RIP_W_INVALIDSIZE(ptr); } else \
  283.     RIP_E_INVALIDSIZE(ptr); }}
  284.  
  285.  
  286. #define V_STRUCTPTR_WRITE_VER(ptr,ver) \
  287. {   ver = 7; DWORD *pdw = &ver;  \
  288.     if (IsBadReadPtr(ptr, sizeof(DWORD)))               RIP_E_BLOCKVSDWSIZE(ptr); \
  289.     if (IsBadWritePtr(ptr, (ptr)->dwSize))              RIP_E_BLOCKVSDWSIZE(ptr); \
  290.     switch ((ptr)->dwSize) {
  291.     
  292. #define V_STRUCTPTR_WRITE_VER_CASE(basetype,ver) \
  293.     case sizeof(basetype##ver) : \
  294.         V_ASSERT(offsetof(basetype##ver, dwSize) == 0); \
  295.         *pdw = ver; break;
  296.     
  297. #define V_STRUCTPTR_WRITE_VER_END(basetype,ptr) \
  298.     default : if ((ptr)->dwSize > sizeof(basetype##7)) \
  299.     { RIP_W_INVALIDSIZE(ptr); } else \
  300.     RIP_E_INVALIDSIZE(ptr); }}
  301.  
  302.  
  303.  
  304. #endif          // _VALIDATE_H_
  305.